home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’95 / Venus / SimpleWindow.cc < prev    next >
Text File  |  1995-06-23  |  9KB  |  332 lines

  1. /*
  2.  ***********************************************************************
  3.  *
  4.  *
  5.  *                                Simple Window Class
  6.  *        
  7.  *
  8.  ***********************************************************************
  9.  */
  10.  
  11. #include "std.h"
  12. #include "image.h"
  13. #include "window.h"
  14. #include <PictUtil.h>
  15.  
  16. /*
  17.  *----------------------------------------------------------------------
  18.  *                            Service functions
  19.  */
  20.  
  21.                                         // Getting a bounding rectangle of an image
  22. ScreenRect::ScreenRect(const IMAGE& image)
  23. {
  24.     top = 0;
  25.     bottom = top + image.q_nrows();
  26.     left = 0;
  27.     right = left + image.q_ncols();
  28. }
  29.  
  30.                                     // Create a rectangle of given height/width
  31.                                     // positioned at the origin
  32. ScreenRect::ScreenRect(const rowcol& heightwidth)
  33. {
  34.     left = top = 0;
  35.     bottom = heightwidth.row();
  36.     right  = heightwidth.col();
  37. }
  38.  
  39.                                     // Create a rectangle of given height/width
  40.                                     // positioned at a given point
  41. ScreenRect::ScreenRect(const rowcol& origin, const rowcol& heightwidth)
  42. {
  43.     top  = origin.row();
  44.     left = origin.col();
  45.     bottom = top+heightwidth.row();
  46.     right  = left+heightwidth.col();
  47. }
  48.  
  49.  
  50.                                     // Shifting a rectangle by the same amount
  51.                                     // in X and Y
  52. ScreenRect& ScreenRect::operator += (const int offset)
  53.     top += offset; bottom += offset; left += offset; right += offset;
  54.     return *this;
  55. }
  56.  
  57.  
  58.                                     // Print what rectangle is this
  59. void ScreenRect::print(const char * title) const
  60. {
  61.     message("Rectangle %s (%d,%d) - (%d,%d)",title,top,left,bottom,right);
  62. }
  63.  
  64.  
  65.  
  66.                                     // Used to "implicitly" convert from C to Pascal
  67.                                     // string
  68. Pstr::Pstr(const char * c_str)
  69. {
  70.     strncpy((char *)pas_string,c_str,sizeof(*this)-2);
  71.     CtoPstr((char *)pas_string);
  72. }
  73.  
  74. /*
  75.  *----------------------------------------------------------------------
  76.  *        A generic simple window that can be dragged around the screen
  77.  *                and closed by clicking a "go-away" button
  78.  * No other events are handled, redefine the event handler if necessary.
  79.  */
  80.  
  81.  
  82.                                     // Create a color window of the specified size and title
  83.                                     // Note, the upper left corner of 'rect' must
  84.                                     // NOT be (0,0)!
  85. ScreenWindow::ScreenWindow(ScreenRect rect, const char * title)
  86. {
  87.     const int window_offset = 100;        // Cannot be 0 or small!
  88.     this_window = NewCWindow(nil,rect += window_offset,(Pstr)title,
  89.                             TRUE,noGrowDocProc,
  90.                             (WindowPtr)(-1),TRUE,(long)this);
  91.     assert( this_window != 0 );
  92.     SetPort(this_window);
  93.     SelectWindow(this_window);
  94. }
  95.  
  96.                                     // Create a color window from a resource template
  97. ScreenWindow::ScreenWindow(const short resource_id)
  98. {
  99.     this_window = GetNewCWindow(resource_id,nil,(WindowPtr)(-1));
  100.     SetWRefCon(this_window,(long)this);
  101.     assert( this_window != 0 );
  102.     SetPort(this_window);
  103.     SelectWindow(this_window);
  104. }
  105.  
  106.  
  107.  
  108.                                     // Close the window and clean up the rubble
  109. ScreenWindow::~ScreenWindow(void)
  110. {
  111.     assert( this_window != 0 );
  112.     DisposeWindow(this_window);
  113.     this_window = 0;
  114. }
  115.  
  116.  
  117.                                     // Event handling loop. Returns only when the
  118.                                     // window is to be destroyed
  119. void ScreenWindow::handle(void)
  120. {
  121.     const long event_timeout = 1;
  122.     EventRecord    theEvent;
  123.     unsigned long int prev_tick_count = 0;
  124.      
  125.     for(;;)
  126.     {
  127.         if( !WaitNextEvent(everyEvent, &theEvent,event_timeout,nil) )
  128.           if( handle_null_event(theEvent.when) )
  129.             continue;
  130.           else
  131.             return;
  132.           switch (theEvent.what)
  133.         {
  134.           case mouseDown:
  135.             if( !handle_mouse_down(theEvent) )
  136.               return;                        // Window is to be closed (go-away buttin clicked)
  137.             break;
  138.             
  139.           case updateEvt:
  140.             if( this_window == (WindowPtr)theEvent.message )
  141.               update();
  142.             break;
  143.  
  144.           case keyDown:
  145.           case autoKey:
  146.             if( !handle_key_down(theEvent) )
  147.               return;                        // a "quit" key must've been pressed
  148.             break;
  149.                         
  150.           case activateEvt:
  151.             if( this_window == (WindowPtr)theEvent.message )
  152.               activate(theEvent.modifiers & 0x01);
  153.             break;
  154.         }  
  155.     }
  156.     
  157. }
  158.  
  159.                                 // Handle "mouse-down" events
  160.                                 // Returns FALSE if the user clicked within the
  161.                                 // go-away region of our window. Otherwise,
  162.                                 // returns TRUE
  163.                                 // Handles dragging if necessary and system clicks
  164. Boolean ScreenWindow::handle_mouse_down(const EventRecord& the_event)
  165. {
  166.     WindowPtr    wp;
  167.     short        windowPart = FindWindow (the_event.where, &wp);
  168.     
  169.     switch (windowPart)
  170.     {
  171.       case inSysWindow: 
  172.         SystemClick(&the_event, wp);
  173.         break;
  174.         
  175.       case inMenuBar:
  176.         break;
  177.  
  178.       case inContent:
  179.           break;
  180.           
  181.       case inDrag:
  182.           if (wp == this_window )
  183.             drag(the_event.where);
  184.           break;
  185.                       
  186.       case inGoAway:
  187.           return FALSE;
  188.     }
  189.     return TRUE;
  190. }
  191.  
  192.                                         // Handles key_down & auto_key events. Return FALSE
  193.                                         // if the window is to be closed down
  194. Boolean ScreenWindow::handle_key_down(const EventRecord& the_event)
  195. {
  196.     return FALSE;                        // Each key kills the application, sorry
  197. }
  198.  
  199.  
  200.                                         // Handles null events, when nothing happens for some
  201.                                         // time. Return FALSE when it's time to die
  202. Boolean ScreenWindow::handle_null_event(const long event_time)
  203. {
  204.     return TRUE;                            // Keep going
  205. }
  206.  
  207.                             // Private window parts
  208.                                     // Handle an update event - redraw the window
  209.                                     // A virtual function draw() is called to do
  210.                                     // the actual redrawing
  211. void ScreenWindow::update(void)
  212. {
  213.     GrafPtr    savePort;
  214.     
  215.     GetPort(&savePort);
  216.     SetPort(this_window);
  217.     BeginUpdate(this_window);
  218.     draw();
  219.     EndUpdate(this_window);
  220.     SetPort(savePort);
  221. }
  222.  
  223.                                     // Make the entire window being redrawn
  224. void ScreenWindow::refresh(void)
  225. {
  226. //    EraseRect(&this_window->portRect);
  227.     InvalRect(&this_window->portRect);            
  228. }
  229.  
  230.                                         // Handle an activate or deactivate event
  231. void ScreenWindow::activate (const Boolean go_active)
  232. {
  233.     if (go_active)
  234.       SetPort(this_window);
  235. }
  236.  
  237.  
  238. /*
  239.  *----------------------------------------------------------------------
  240.  *            A simple window with an offscreen window buffer
  241.  */
  242.  
  243.                                 // Allocate the buffer for the offscreen
  244.                                 // drawing and load CLUT (if clut_id != 0)
  245. OffScreenWindow::OffScreenWindow
  246.     (ScreenRect rect, const char * title, const short clut_id)
  247.     : ScreenWindow(rect,title), graf_world(nil)
  248. {
  249.     CTabHandle clut_handle = nil;
  250.     if( clut_id != 0 )
  251.     {                                // try to get a user CLUT with that resource id
  252.        clut_handle = GetCTable(clut_id);
  253.        assert( clut_handle != 0 );
  254.        SetWinColor(our_window(),(WinCTab**)clut_handle);
  255.     }
  256.     do_well( NewGWorld(&graf_world,8,rect,clut_handle,nil,0) );
  257.     assert( graf_world != (void *)0 );
  258.  
  259. //    if( clut_handle != nil )
  260. //      DisposCTable(clut_handle);        // CLUT has been copied, and can be disposed of now
  261.                                         // But careful! CLUT is associated with the window
  262.                                         // by SetWinColor(), so we don't dispose of it
  263.  
  264.                                         // Get hold of the offscreen pixmap
  265.     pixmap = GetGWorldPixMap(graf_world);        // and make sure it looks like
  266.     assert( pixmap != nil && *pixmap != nil );    // we can use it
  267.  
  268.     assert( (**pixmap).cmpCount == 1 );            // We have a color table index
  269.     assert( !PixMap32Bit(pixmap) );
  270.  
  271.     _height = abs((**pixmap).bounds.top - (**pixmap).bounds.bottom);
  272.     _width  = abs((**pixmap).bounds.right - (**pixmap).bounds.left);
  273.     _bytes_per_row = (**pixmap).rowBytes & 0x7fff;
  274.  
  275.     assert( _height > 0 && _height < 10000 );         // Just to play safe
  276.     assert( _width > 0 && _width <= _bytes_per_row );    
  277.  
  278.     activate_palette();                    // Activate palette for the window
  279. }
  280.  
  281.                                 // Dispose of the offscreen buffer
  282. OffScreenWindow::~OffScreenWindow(void)
  283. {
  284.     assert( graf_world != nil );
  285.     DisposeGWorld(graf_world);
  286.     graf_world = nil;
  287.     PaletteHandle window_palette = GetPalette(our_window());
  288.     if( window_palette != nil )                // dispose of our palette if was allocated
  289.     {
  290.         SetPalette(our_window(),nil,FALSE);
  291.         DisposePalette(window_palette);
  292.     }
  293.     pixmap = nil;
  294.     _height = _width = _bytes_per_row = 0;
  295. }
  296.  
  297.                                     // Make sure that the colors of our off-screen
  298.                                     // buffer would be displayed properly (or close enough)
  299.                                     // on screen
  300. void OffScreenWindow::activate_palette(void)
  301. {
  302.     CTabHandle window_ctab = (**pixmap).pmTable;
  303.     assert( window_ctab != nil && *window_ctab != nil );
  304.  
  305.     PaletteHandle palette = NewPalette((**window_ctab).ctSize,window_ctab,pmTolerant+pmExplicit,0);
  306.     assert( palette != nil );
  307.     SetPalette(our_window(),palette,TRUE);
  308.     do_well( QDError() );
  309.     ActivatePalette(our_window());    
  310.     do_well( QDError() );
  311. }
  312.  
  313.  
  314.                                 // Get a bounding rectangle for the window
  315. ScreenRect OffScreenWindow::q_bounds(void) const
  316. {
  317.     return (**pixmap).bounds;
  318. }
  319.  
  320.  
  321.                                     // Actual drawing - moving the picture from the
  322.                                     // offscreen grafworld to the onscreen one
  323. void OffScreenWindow::draw(void)
  324. {
  325.     assert( LockPixels(pixmap) );
  326.     Rect& pixmap_rect = (**pixmap).bounds;
  327.     CopyBits((const BitMap *)*pixmap, &qd.thePort->portBits, &pixmap_rect, 
  328.              &our_window()->portRect, /*ditherCopy*/ srcCopy, nil);
  329.     UnlockPixels(pixmap);
  330. }
  331.